home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / cshell / run.c < prev    next >
C/C++ Source or Header  |  1994-03-07  |  18KB  |  772 lines

  1. /*
  2.  * RUN.C
  3.  *
  4.  * (c)1986 Matthew Dillon     9 October 1986
  5.  *
  6.  *    RUN   handles running of external commands.
  7.  *
  8.  * Version 2.07M by Steve Drew 10-Sep-87
  9.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  10.  * Version 5.00L by Urban Mueller 17-Feb-91
  11.  * Version 5.20L by Andreas M. Kirchwitz (Fri, 13 Mar 1992)
  12.  *
  13.  */
  14.  
  15. #include "shell.h"
  16.  
  17. int MySyncRun( char *com, char *args, BPTR in, BPTR out, int nosync );
  18. int echofunc(void);
  19.  
  20. int
  21. do_run( char *str, int nosync )
  22. {
  23.     int retcode;
  24.     char buf[200];        /* enough space for 100 char cmd name + path stuff */
  25.     char *path, *path2, *argline, *copy, *ext, *end;
  26.  
  27.     if( !*av[0] )
  28.         return 0;
  29.  
  30.     if( (retcode=echofunc())>=0 )
  31.         return retcode;
  32.  
  33.     a0tospace( av[0] );                                 /* allow "com mand" */
  34.  
  35.     argline=compile_av(av, 1, ac, ' ', 1);
  36.  
  37.     if (strlen(av[0]) > 100) { ierror(NULL,509); return -1; }
  38.  
  39.     if( ac==1 && isdir(av[0])) {
  40.         sprintf(buf,"cd \"%s\"",av[0]);
  41.         return execute( buf );
  42.     }
  43.  
  44.     IoError=IoErr();
  45.     if( (IoError==218 || IoError==225 || IoError==226) && index(av[0],':')) {
  46.         ierror( av[0], IoError );
  47.         return 20;
  48.     }
  49.  
  50.     sprintf(buf,"res_%s",FilePart(av[0]));               /* delayed residents */
  51.     /* AMK: OS20-GetVar replaces ARP-Getenv */
  52.     if (o_resident && GetVar(buf,buf+100,90L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR)>=0L) {
  53.         /* AMK: OS20-SetVar replaces ARP-Setenv */
  54.         SetVar(buf,NULL,NULL,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  55.         loadres(buf+100);
  56.     }
  57.  
  58.     if( (retcode=MySyncRun(av[0],argline,0,0,nosync))>=0 )   /* AmigaDOS path */
  59.         goto done2;
  60.  
  61.     if( retcode==-2 /*PR_NOMEM*/ ) {
  62.         ierror( av[0], 103 );
  63.         return 20;
  64.     }
  65.  
  66.     IoError=IoErr();
  67.     if( (IoError==218 || IoError==225 || IoError==226) && index(av[0],':')) {
  68.         ierror( av[0], IoError );
  69.         return 20;
  70.     }
  71.  
  72.     if (path = dofind(av[0],"",buf+80,v_path)) {             /* shell path    */
  73.         DPTR *dp;
  74.         BPTR fh;
  75.         int stat, script;
  76.         if((retcode = MySyncRun(path,argline,0,0,nosync))>=0)
  77.             goto done2;
  78.         if(dp=dopen(path,&stat)) {
  79.             script= dp->fib->fib_Protection&FIBF_SCRIPT;
  80.             dclose(dp);
  81.             if( !stat && script ) {
  82.                 char *t;
  83.                 buf[0]=0;
  84.                 if( fh=Open(path,MODE_OLDFILE )) {
  85.                     Read(fh,buf,79);
  86.                     Close(fh);
  87.                     if(t=index(buf,'\n')) *t=0;
  88.                 }
  89.                 if( buf[0]=='/' && buf[1]=='*' ) {
  90.                     sprintf(buf, "Rx %s", str );
  91.                 } else if( (buf[0]!=';' || buf[0]!='#') && buf[1]=='!' ) {
  92.                     memmove(buf,buf+2,strlen(buf+2)+1);
  93.                     strcat( buf," ");
  94.                     strcat( buf,str);
  95.                 } else {
  96.                     sprintf(buf,"Execute %s", str );
  97.                 }
  98.                 return execute( a0tospace(buf));
  99.             }
  100.         }
  101.     }
  102.  
  103.     if(!(end=rindex(av[0],'.'))) end="";               /* automatic sourcing */
  104.     ext=strcmp(end,".sh") ? ".sh" : "";
  105.     if (path = dofind(av[0],ext,buf,v_path)) {
  106.         av[1] = buf;
  107.         copy = salloc(strlen(str)+3);
  108.         sprintf(copy,"x %s",str);
  109.         retcode = do_source(copy);
  110.         goto done;
  111.     }
  112.  
  113.     copy=salloc(strlen(av[0])+strlen(argline)+5);
  114.     sprintf(copy,"%s %s",av[0],argline);
  115.  
  116.     ext=strcmp(end,".rexx") ? ".rexx" : "";           /* automatic rx-ing   */
  117.     if( path = dofind(av[0], ext, buf, v_rxpath )) {
  118.         strcat (path," ");
  119.         if( strlen(argline)>140 ) argline[140]=0;
  120.         strcat (path,argline);
  121.  
  122. /*        strncpy(path+strlen(path),argline,190); */
  123.         if( (retcode=MySyncRun("rx",path,0,0,0)) >=0 ) goto done;
  124.         if (path2 = dofind("rx","",buf+160,v_path)) {
  125.             retcode = MySyncRun(path2,path,0,0,0);
  126.             goto done;
  127.         }
  128.  
  129.     }
  130.  
  131.     if( !doaction(av[0],"exec",argline)) {
  132.         retcode=0;
  133.         goto done;
  134.     }
  135.  
  136.     retcode=-1;
  137.     fprintf(stderr,"Command not found %s\n",av[0]);
  138.  
  139. done:
  140.     free( copy );
  141. done2:
  142.     setioerror( IoErr() );
  143.     free( argline );
  144.     return retcode;
  145. }
  146.  
  147.  
  148.  
  149. #ifndef END_STREAM_CH
  150. #define END_STREAM_CH -1L
  151. #endif
  152. BPTR
  153.     new_input,    /* for execute'ing a script file */
  154.     old_inp_fh,    /* old input filehandle */
  155.     old_out_fh,    /* old output filehandle */
  156.     seglist_cmd;    /* to be returned from NewLoadSeg */
  157.  
  158.  
  159. void set_returncodes(long returncode,long result2)
  160. {
  161.     Mycli->cli_ReturnCode = returncode;
  162.     Mycli->cli_Result2    = result2;
  163. }
  164.  
  165.  
  166.  
  167. void clean_up_io(void)
  168. {
  169.     long ch;
  170.     Flush(Output());
  171.     ch = UnGetC(Input(),END_STREAM_CH) ? 0 : '\n';
  172.     while ((ch != '\n') && (ch != END_STREAM_CH))
  173.         ch = FGetC(Input());
  174. }
  175.  
  176. long command_examine(char *fname,BPTR *plock)
  177. {
  178.     /*
  179.     Given a filename, attempt to determine if we can process it. Either
  180.     by running it, or by 'executing' it (a script).
  181.  
  182.     Returns:
  183.         0 = can RunCommand the file
  184.         1 = can source/script/execute the file
  185.       < 0 = error
  186.     */
  187.     struct FileInfoBlock *fib;
  188.     long i;
  189.     BPTR lock;
  190.  
  191.     *plock = NULL;
  192.  
  193.     if (!(lock=Lock(fname,ACCESS_READ)))
  194.         return -1;
  195.  
  196.     if (!(fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,NULL))) {
  197.         UnLock(lock);
  198.         return -9;
  199.     }
  200.  
  201.     if (!Examine(lock,fib)) {
  202.         UnLock(lock);
  203.         FreeDosObject(DOS_FIB,fib);
  204.         return -2;
  205.     }
  206.  
  207.     i = fib->fib_DirEntryType;
  208.  
  209.     if (i==ST_SOFTLINK) {
  210.         /*
  211.            Let our caller resolve the link, and if it resolves to a file,
  212.            call us again.
  213.         */
  214.         UnLock(lock);
  215.         FreeDosObject(DOS_FIB,fib);
  216.         return -10;
  217.     }
  218.  
  219.     if (!((i==ST_FILE) || (i==ST_LINKFILE))) {
  220.         UnLock(lock);
  221.         FreeDosObject(DOS_FIB,fib);
  222.         return -3;
  223.     }
  224.  
  225.     i = fib->fib_Protection;
  226.     i = (i & 0x70) | (0x0f & ~i);
  227.     if (!((i & FIBF_SCRIPT) || (i & FIBF_EXECUTE))) {
  228.         /* Not an executable or a script file. */
  229.         UnLock(lock);
  230.         FreeDosObject(DOS_FIB,fib);
  231.         return -4;
  232.     }
  233.  
  234.     FreeDosObject(DOS_FIB,fib);
  235.     seglist_cmd = NULL;
  236.     new_input = NULL;
  237.     *plock = ParentDir(lock);
  238.  
  239.     if (i & FIBF_SCRIPT) {
  240.         /*
  241.             Open the file, but let the 'outside world' dick with CurrentInput.
  242.             Not me. Outside of my definition. :)
  243.         */
  244.         if (!(new_input=OpenFromLock(lock))) {
  245.             UnLock(lock);
  246.             UnLock(*plock);
  247.             return -5;
  248.         }
  249.         /* Remember that 'lock' is now INVALID and should not be touched. */
  250.         return 1;
  251.     }
  252.  
  253.     if (i & FIBF_EXECUTE) {
  254.         /* LoadSeg the sucker. */
  255.         if (!(seglist_cmd=NewLoadSeg(fname,NULL))) {
  256. #if 0
  257.             /* AMK: distinguish between "no memory" and "not an executable" */
  258.             if (IoErr()==ERROR_NO_FREE_STORE) {
  259.                 UnLock(lock);
  260.                 UnLock(*plock);
  261.                 return -11;
  262.             }
  263. #endif
  264.             /* Probably a 'bad' file (i.e., not actually an executable). */
  265.             UnLock(lock);
  266.             UnLock(*plock);
  267.             return -6;
  268.         }
  269.         UnLock(lock);
  270.         return 0;
  271.     }
  272.  
  273.     if (lock) UnLock(lock);
  274.     if (*plock) UnLock(*plock);
  275.     return -7;    /* should NEVER reach this point */
  276. }
  277.  
  278.  
  279.  
  280. long command_device(char *device,char *fname)
  281. {
  282.     /*
  283.     For the Device specified by *device, search each element of the
  284.     assign (since it could be a multi-assign) and try to find a
  285.     command file. A command file can be either an executable file, or
  286.     a script file (one with the script bit set).
  287.  
  288.     Returns:
  289.         0 = can RunCommand this file (seglist_cmd set)
  290.         1 = can source/script/execute this file (new_input set)
  291.       < 0 = error
  292.        -8 = Bad device name
  293.  
  294.     Note that this routine generates only one error of its own. All
  295.     other results are passed straight thru from command_examine ().
  296.     */
  297.  
  298.     long gotlock,            /* we have a directory lock or not */
  299.          result = 0,        /* from command_examine () */
  300.          /* AMK: result initialized with 0 */
  301.          done = 0;            /* found something we could use */
  302.     struct DevProc *dp = NULL;    /* for searching multi-assigned paths */
  303.     struct MsgPort *fstask;        /* for GetFileSysTask () */
  304.     BPTR plock,            /* parent of fname */
  305.          lock,            /* on source directory */
  306.          dir_lock;            /* save current directory */
  307.  
  308.     /*printf("search: %s -> %s\n",device,fname);*/
  309.  
  310.     fstask = GetFileSysTask ();
  311.  
  312.     do {
  313.         dp = GetDeviceProc(device,dp);
  314.         if (dp) {
  315.             SetFileSysTask(dp->dvp_Port);
  316.  
  317.             lock = NULL;
  318.             gotlock = 0;
  319.             if (dp->dvp_Lock) {
  320.                 dir_lock = CurrentDir(dp->dvp_Lock);
  321.                 gotlock = 1;
  322.             }
  323.             else {
  324.                 if (lock=Lock(device,ACCESS_READ)) {
  325.                     dir_lock = CurrentDir(lock);
  326.                     gotlock = 1;
  327.                 }
  328.             }
  329.             if (gotlock) {
  330.                 result = command_examine(fname,&plock);
  331.                 /*
  332.                     NOTE: Philosophically speaking, if result <= -2, what
  333.                     should we do? This means that command_examine () actually
  334.                     found a file by the correct name, but it was unsuitable for
  335.                     some reason.
  336.                     Currently, we continue to search, in hopes that St. Nicholas
  337.                     will soon be here...(ie, we will find a file that meets our
  338.                     criteria). This is questionable as to its correctness.
  339.                 */
  340.                 if (result<0) {
  341.                     done = 0;
  342.                 }
  343.                 else {
  344.                     BPTR hdir_lock;
  345.                     if (plock)
  346.                         hdir_lock = plock;
  347.                     else if (lock)
  348.                         hdir_lock = lock;
  349.                     else if (dp->dvp_Lock)
  350.                         hdir_lock = dp->dvp_Lock;
  351.                     else
  352.                         hdir_lock = NULL;
  353. /*
  354.                     {char buf[256];
  355.                     if (hdir_lock && NameFromLock(hdir_lock,buf,256))
  356.                         printf("hdir_lock: %s\n",buf);
  357.                     }
  358. */
  359.                     done = 1;
  360.                     /*
  361.                     --- This was from XSHell, but wasn't correct ---
  362.                     Myprocess->pr_HomeDir = DupLock(lock?lock:dp->dvp_Lock);
  363.                     */
  364.                     Myprocess->pr_HomeDir = DupLock(hdir_lock);
  365.                     UnLock(plock);
  366.                 }
  367.                 if (lock) {
  368.                     UnLock(lock);
  369.                     lock = NULL;
  370.                 }
  371.                 CurrentDir(dir_lock);
  372.             }
  373.         }
  374.     } while (!done                               &&
  375.          dp && (dp->dvp_Flags & DVPF_ASSIGN) &&
  376.          IoErr() == ERROR_OBJECT_NOT_FOUND);
  377.  
  378.     SetFileSysTask (fstask);
  379.     if (dp) FreeDeviceProc(dp);
  380.  
  381.     if (!done && result >= 0) {
  382.         /* Can happen when GetDeviceProc returns a NULL dp on the first go. */
  383.         result = -8;
  384.     }
  385.  
  386.     return result;
  387. }
  388.  
  389.  
  390.  
  391. long command_processor(long abs_cmd,char *device,char *fname)
  392. {
  393.     /*
  394.     Results:
  395.         Those returned by command_examine () and command_device ().
  396.  
  397.         0 = can RunCommand (seglist_cmd set)
  398.         1 = can source/script/execute (new_input set)
  399.       < 0 = error
  400.     */
  401.  
  402.     struct PathList *pl;    /* to parse the PATH */
  403.     long result,        /* from command_examine () or command_device () */
  404.          sub_cmd;        /* command is in a sub-directory */
  405.     BPTR plock;        /* points to parent directory of fname */
  406.     char buf [256];        /* where to put elements of the Cli Path */
  407.     long i;            /* browse thru prghash_num's */
  408.     char *filepart;        /* file-part of prghash_list items */
  409.     long fnamelen;        /* length of fname */
  410.  
  411.     sub_cmd = abs_cmd & 2;    /* a '/' was found in the input filename */
  412.     abs_cmd &= 1;        /* so it only has one meaning: a ':' was found */
  413.  
  414.     if (*device == '\0')
  415.         abs_cmd = 0;    /* handle special case of empty device */
  416.  
  417.     if (abs_cmd) {        /* absolute path like 'dh0:myprog' */
  418.         result = command_device(device,fname);
  419.         return result;
  420.     }
  421.     if (sub_cmd) {        /* relative path like 'mydir/myprog' */
  422.         result = command_examine (fname, &plock);
  423.         if (result < 0) return result;
  424.         /*
  425.             NOTE: Is the following OK? Or should we DupLock() and then
  426.             UnLock()? I don't see why....
  427.         */
  428.         Myprocess->pr_HomeDir = plock;
  429.         plock = NULL;
  430.         return result;
  431.     }
  432.     /* file in current directory */
  433.     result = command_examine(fname,&plock);
  434.     if (result >= 0) {
  435.         Myprocess->pr_HomeDir = plock;
  436.         plock = NULL;
  437.         return result;
  438.     }
  439.  
  440.     /* BEGIN -- AMK TEST FOR HASH-LIST -- BEGIN */
  441.  
  442.     fnamelen = strlen(fname);
  443.  
  444.     for(i=0; i<prghash_num; i++) {
  445.         if (filepart=FilePart(prghash_list[i])) {
  446.             if ((o_abbrev&2 && strnicmp(fname,filepart,fnamelen)==0)
  447.             || (!(o_abbrev&2) && stricmp(fname,filepart)==0))
  448.             {
  449.                 /*printf("hash hit: %s -> %s\n",fname,prghash_list[i]);*/
  450.                 result = command_examine(prghash_list[i],&plock);
  451.                 if (result >= 0) {
  452.                     Myprocess->pr_HomeDir = plock;
  453.                     plock = NULL;
  454.                     return result;
  455.                 }
  456.             }
  457.         }
  458.     }
  459.  
  460.     if (prghash_num>0 && !(o_abbrev&4))
  461.         return result;
  462.  
  463.     for(i=0; i<prghash_num; i++) {
  464.         if (filepart=FilePart(prghash_list[i])) {
  465.             if (strnicmp(fname,filepart,fnamelen)==0) {
  466.                 /*printf("hash hit: %s -> %s\n",fname,prghash_list[i]);*/
  467.                 result = command_examine(prghash_list[i],&plock);
  468.                 if (result >= 0) {
  469.                     Myprocess->pr_HomeDir = plock;
  470.                     plock = NULL;
  471.                     return result;
  472.                 }
  473.             }
  474.         }
  475.     }
  476.  
  477.     if (prghash_num>0)
  478.         return result;
  479.     /* END -- AMK TEST FOR HASH-LIST -- END */
  480.  
  481.     /* DOS search path */
  482.     /* Forbid(); */
  483.     pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  484.     while (pl && !dobreak()) {
  485.         if (pl->pl_PathLock) {
  486.             if (NameFromLock(pl->pl_PathLock,buf,256)) {
  487.                 result = command_device(buf,fname);
  488.                 if (result >= 0) {
  489.                     /* Permit(); */
  490.                     return result;
  491.                 }
  492.             }
  493.             else {
  494.                 fprintf(stderr,"csh.command_processor: NameFromLock() failed\n");
  495.             }
  496.         }
  497.         pl = (struct PathList *)BADDR(pl->pl_NextPath);
  498.     }
  499.     /* Permit(); */
  500.  
  501.     /* Last, but CERTAINLY not least, search 'C:' */
  502.     if (!dobreak())
  503.         result = command_device("C:",fname);
  504.  
  505.     return result;
  506. }
  507.  
  508.  
  509.  
  510. int
  511. MySyncRun( char *com, char *args, BPTR in, BPTR out, int nosync )
  512. {
  513.     struct Segment *cmdseg = NULL;
  514.     int len=strlen(args);
  515.     char myname[256];
  516.     BPTR myhdir,mymod;
  517.     long abs_cmd = 0;
  518.     char *p,*pname=strdup(com), *ppath=strdup(com), *pdev=strdup(com);
  519.     long rslt = -1;
  520.  
  521. /*
  522.     old_inp_fh = SelectInput (Mycli->cli_CurrentInput);
  523.     old_out_fh = SelectOutput(Mycli->cli_StandardOutput);
  524.     Flush(Input());
  525.     Flush(Output());
  526. */
  527.     GetProgramName(myname,255);
  528.     myhdir = Myprocess->pr_HomeDir;
  529.     mymod  = Mycli->cli_Module;
  530.  
  531.     /* clear it so that we don't "free" ourself on MySyncRun_done: */
  532.     Myprocess->pr_HomeDir = NULL;
  533.     Mycli->cli_Module = NULL;
  534.  
  535.     args[len]='\n'; args[len+1]=0;        /* trailing '\n' */
  536.  
  537.     if (!pname || !ppath || !pdev)
  538.         goto MySyncRun_done;
  539.  
  540.     if (p=FilePart(com))
  541.         strcpy(pname,p);
  542.  
  543.     if (p=strchr(pdev,':')) {
  544.         abs_cmd |= 1;
  545.         strcpy(ppath,++p);
  546.         *p='\0';
  547.     }
  548.     else strcpy(pdev,"");
  549.  
  550.     if (strchr(ppath,'/'))
  551.         abs_cmd |= 2;
  552.  
  553. /*
  554. printf("prog: %s, arg: %s, async: %s\n",com,args,nosync?"yes":"no");
  555. printf("pdev: %s, ppath: %s, pname: %s [%ld]\n",pdev,ppath,pname,abs_cmd);
  556. */
  557.  
  558.     seglist_cmd = NULL;
  559.     new_input = NULL;
  560.  
  561.     if (!abs_cmd || strnicmp(com,"C:",2)==0) {
  562.         char *comname = (strnicmp(com,"C:",2)==0) ? FilePart(com) : com ;
  563.         Forbid();
  564.         if (!(cmdseg = FindSegment(comname,NULL,FALSE)))
  565.             cmdseg = FindSegment(comname,NULL,TRUE);
  566.         if (cmdseg) {
  567. /*
  568.     Randell says ...
  569.             if ((cmdseg->seg_UC < CMD_DISABLED) ||
  570.     ... but if a command is disabled why we should execute it?
  571. */
  572.             if ((cmdseg->seg_UC <= CMD_DISABLED) ||
  573.                 (cmdseg->seg_UC == CMD_SYSTEM))
  574.                 cmdseg = NULL;
  575.             else if (cmdseg->seg_UC >= 0)
  576.                 cmdseg->seg_UC++;
  577.         }
  578.         Permit();
  579.         if (cmdseg) {
  580.             seglist_cmd = cmdseg->seg_Seg;
  581.             Myprocess->pr_HomeDir = NULL;
  582.         }
  583.     }
  584.  
  585.     if (!cmdseg) {
  586.         rslt = command_processor(abs_cmd,pdev,ppath);
  587.         /*printf("cmd_processor returned %ld, %ld\n",rslt,IoErr());*/
  588.         if (rslt<0) {
  589.             /*printf("Object not found (rc=%d): %s\n",rslt,pname);*/
  590.             goto MySyncRun_done;
  591.             /*return -1;*/
  592.         }
  593.     }
  594.  
  595.     if (new_input) {                /* rslt = 1 */
  596.         char scp_name[256];
  597.         char *exec_buf;
  598.  
  599.         NameFromFH(new_input,scp_name,255);
  600.         Close(new_input);
  601.  
  602.         /*printf("launch script (%s) %s, %s, %s ...\n",scp_name,pdev,ppath,pname);*/
  603. #if 0
  604.         sys_tags[1].ti_Tag  = SYS_Output;
  605.         sys_tags[1].ti_Data = (ULONG)Myprocess->pr_COS;
  606. #endif
  607.  
  608.         if (exec_buf = malloc(strlen(scp_name)+strlen(args)+12)) {
  609.             sprintf(exec_buf,"execute \"%s\" %s",scp_name,args);
  610.             rslt = SystemTags(exec_buf,SYS_Input,(ULONG)Input(),SYS_Output,(ULONG)Output(),TAG_END);
  611.             free(exec_buf);
  612.         }
  613.         else {
  614.             fprintf(stderr,"we are out of memory for System()\n");
  615.             set_returncodes(RETURN_FAIL,ERROR_NO_FREE_STORE);
  616.             rslt = RETURN_FAIL;
  617.         }
  618.  
  619.         /*clean_up_io();*/
  620.     }
  621.  
  622.     if (seglist_cmd) {                /* rslt = 0 */
  623.         SetIoErr(0);
  624.  
  625.         if (!SetProgramName(pname))
  626.             SetProgramName("CSH-program");
  627.  
  628.         if (Mycli->cli_DefaultStack < 1000)
  629.             Mycli->cli_DefaultStack=4000;
  630.  
  631.         Mycli->cli_Module = seglist_cmd;
  632.         rslt = RunCommand(seglist_cmd,Mycli->cli_DefaultStack*4,args,strlen(args));
  633.  
  634.         if ((rslt==-1) && (IoErr()==ERROR_NO_FREE_STORE)) {
  635.             fprintf(stderr,"we are out of memory for RunCommand()\n");
  636.             set_returncodes(RETURN_FAIL,ERROR_NO_FREE_STORE);
  637.             rslt = RETURN_FAIL;
  638.             goto MySyncRun_done;
  639.         }
  640.  
  641.         set_returncodes(rslt,IoErr());
  642.  
  643.         SetProgramName(myname);
  644.     }
  645.  
  646. MySyncRun_done:
  647.     if (cmdseg) {
  648.         Forbid();
  649.         if (cmdseg->seg_UC>0)
  650.             cmdseg->seg_UC--;
  651.         Permit();
  652.         Mycli->cli_Module = NULL;
  653.     }
  654.  
  655.     if (!cmdseg && seglist_cmd) {
  656.         if (Mycli->cli_Module)
  657.             UnLoadSeg(Mycli->cli_Module);
  658.         Mycli->cli_Module = NULL;
  659.     }
  660.  
  661.     if (Myprocess->pr_HomeDir) {
  662.         /*
  663.         char hd[256];
  664.         if (NameFromLock(Myprocess->pr_HomeDir,hd,255))
  665.             printf("homedir set to %s, now unlocking.\n",hd);
  666.         else {
  667.             fprintf(stderr,"csh.MySyncRun: NameFromLock() failed\n");
  668.             printf("homedir's name too long, now unlocking.\n");
  669.         }
  670.         */
  671.         UnLock(Myprocess->pr_HomeDir);
  672.         Myprocess->pr_HomeDir = NULL;
  673.     }
  674.  
  675.     Myprocess->pr_HomeDir = myhdir;
  676.     Mycli->cli_Module     = mymod;
  677.  
  678.     if (pname) free(pname);
  679.     if (ppath) free(ppath);
  680.     if (pdev)  free(pdev);
  681.  
  682.     /*clean_up_io();*/
  683.  
  684. /*
  685.     old_out_fh = SelectOutput (Mycli->cli_StandardOutput);
  686.     old_inp_fh = SelectInput  (Mycli->cli_CurrentInput);
  687. */
  688.  
  689.     return rslt;
  690. #if 0
  691.     if (done) return rslt;
  692.  
  693.     char buf2[200];
  694.     args[len]=0;        /* remove trailing '\n' */
  695.  
  696.     printf("trying old style...\n");
  697.  
  698.     if( nosync ) {
  699.         sprintf(buf2,"%s %s",com,args);
  700.         Execute(buf2,0,Myprocess->pr_COS);
  701.         return 0;
  702.     }
  703.  
  704.     if( (ret= SyncRun( com, args, in, out ))>=0 )
  705.         return ret;
  706.  
  707.     if( ret==PR_NOMEM /* -2L */ ) {
  708.         ierror(NULL,103);
  709.         return 20;
  710.     }
  711.  
  712.     return -1;
  713. #endif
  714. }
  715.  
  716.  
  717. #if 0
  718. int
  719. do_which( char *str )
  720. {
  721.     char *got, *com=av[1];
  722.  
  723.     if( get_var(LEVEL_ALIAS,com) ) {
  724.         printf("Shell Alias '%s'\n",com);
  725.         return 0;
  726.     }
  727.  
  728.     if( *(got=find_internal( com ))>1 ) {
  729.         printf("Shell Internal '%s'\n",got);
  730.         return 0;
  731.     }
  732.  
  733.  
  734.  
  735.     printf( "Not found\n" );
  736.     return 20;
  737. }
  738. #endif
  739.  
  740.  
  741. char *
  742. dofind( char *cmd, char *ext, char *buf, char *path)
  743. {
  744.     char *ptr, *s=path, *ret=NULL;
  745.  
  746.     Myprocess->pr_WindowPtr = (APTR)(-1);
  747.     sprintf(buf,"%s%s",cmd,ext);
  748.     if (exists(buf)) {
  749.         ret=buf;
  750.         goto terminate;
  751.     }
  752.     if ((char*)FilePart(buf)==buf) {
  753.         if( *path=='_' )
  754.             s = get_var(LEVEL_SET, path);
  755.         while (s && *s) {
  756.             for (ptr=buf; *s && *s!=','; ) *ptr++ = *s++;
  757.             if( ptr[-1]!=':' && ptr[-1]!='/')
  758.                 *ptr++='/';
  759.             sprintf(ptr, "%s%s", cmd, ext);
  760.             if (exists(buf)) {
  761.                 ret=buf;
  762.                 goto terminate;
  763.             }
  764.             if (*s) s++;
  765.         }
  766.     }
  767. terminate:
  768.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : Mywindow;
  769.     return ret;
  770. }
  771.  
  772.